﻿<cfscript>

/** 
* Security Frameworks - CAS Client
*
* @displayname "public.service.session.cas" 
* @hint "CAS Client" 
* 
* @Output false
* 
* @accessors true
*/

component {
	
	property type="string" name="CasServerLoginUrl" hint="CAS 用户认证服务器地址";
	property type="string" name="CasServerUrlPrefix" hint="CAS 服务器地址前缀";
	property type="string" name="Service" hint="指定本地服务地址";
	property type="string" name="ServerName" hint="本地服务器名称";
	property type="string" name="Renew" hint="强制要求客户使用用户名/密码认证";
	property type="string" name="Gateway" hint="使用透明认证网关模式";

	property name="TicketValidator" hint="Service Ticket 验证组件";

	/**
	* @hint "初始化对象"
	* 
	* @Output false
	* 
	* @casServerLoginUrl "CAS 用户认证地址"
	* @casServerUrlPrefix "CAS 服务器地址前缀"
	* @service "请求的服务"
	* @serverName "本地服务器名称"
	* @renew "强制要求客户使用用户名/密码认证"
	* @gateway "使用透明认证网关模式"
	*/
	public function init( required string casServerLoginUrl, required string casServerUrlPrefix, string service="", string serverName="", string renew="", string gateway="" ) {
		
		setCasServerLoginUrl( arguments.casServerLoginUrl );
		setCasServerUrlPrefix( arguments.casServerUrlPrefix );
		
		if ( len( arguments.service ) ) {
			setService( arguments.service );
		}
		else if ( len( arguments.serverName ) ) {
			setServerName( arguments.serverName );
		}
		else {
			throw( message="Neither service or serverName is provided" );
		}
		
		if ( arguments.renew eq "true" OR arguments.renew eq "false" ) {
			setRenew( arguments.renew );
		}

		if ( arguments.gateway eq "true" OR arguments.gateway eq "false" ) {
			setGateway( arguments.gateway );
		}
		
	}
	
	/**
	* @hint "生成 CAS 登录地址"
	* 
	* @Output false
	*/
	public string function getLoginURL() {
		
		var loginURL = getCasServerLoginUrl() & "?service=" & URLEncodedFormat( getServiceURL(), "utf-8" );
		
		if ( getRenew() eq "true" ) {
			loginURL = loginURL & "&renew=" & getRenew();
		}

		if ( getGateway() eq "true" ) {
			loginURL = loginURL & "&gateway=" & getGateway();
		}
		
		return loginURL;
	}

	/**
	* @hint "生成 CAS 注销地址"
	* 
	* @Output false
	*/
	public string function getLogoutURL() {
		
		var logoutURL = getCasServerUrlPrefix() & "logout";
		
		return logoutURL;
	}
	
	
	/**
	* @hint "生成 CAS 用户ID"
	* 
	* @Output false
	*/
	public string function getUserId( required string ticketId ) {
		
		var response = getValidateResponse( arguments.ticketId );
		
		if ( structKeyExists( response, "userId" ) ) {
			return response["userId"];
		}
		
		return "";
	}
	
	/**
	* @hint "验证 Service Ticket 并返回认证信息"
	* 
	* @Output false
	* 
	* @ticketId "Service Ticket ID"
	*/
	public struct function getValidateResponse( required string ticketId ) {
		
		var validator = getTicketValidator();
		
		var result = {};
		
		try {
			return validator.validate( arguments.ticketId, getServiceURL() );
		}
		catch ( any exception ) {

			structInsert( result, "exception", exception.message );
		}		

		return result;
	}

	/*	
	=======================================================
	Private Method
	=======================================================
	*/

	/**
	* @hint "生成 CAS 认证请求地址"
	* 
	* @Output false
	*/
	private string function getServiceURL() {
		
		/* 如果没有指定服务地址 则生成动态地址 */
		if ( getService() eq "" ) {
			
			var autoServiceURL = getServerName() & CGI.SCRIPT_NAME;
			
			var queryStr = "";
			
			/* 清理URL地址中的 ticket 相关参数 */
			for ( var i=1; i LTE listLen( CGI.QUERY_STRING, "&" ); i++ ) {
				
				if ( listFirst( listGetAt( CGI.QUERY_STRING, i, "&" ), "=" ) neq "ticket" ) {
					
					queryStr = listAppend( queryStr, listGetAt( CGI.QUERY_STRING, i, "&" ), "&" );
				
				}				
			}
			
			if ( len( queryStr ) ) {
				autoServiceURL = autoServiceURL & "?" & queryStr;
			}
			
			return autoServiceURL;
		}
		
		return getService();
		
	}
	
}

</cfscript>